home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / Goodies / ICONWO~1 / ICONWRKS.BAS < prev    next >
BASIC Source File  |  1997-06-09  |  36KB  |  947 lines

  1. Attribute VB_Name = "Helpers"
  2. Option Explicit
  3. DefLng H-I 'h=handle, i = sysint
  4.  
  5. Dim HelpFilePath As String
  6.  
  7. ' When either the Editor's colorpalette or the ColorPalette Forms
  8. ' ColorPalette need repainting, this routine is called, passing in
  9. ' the picture control used for the specific colorpalette.
  10. '
  11. Sub Display_Color_Palette(Pic_ColorPalette As Control)
  12. Dim i%
  13.     
  14.     ' The ColorPalettes consist of 3 rows of 16 colors, so to make
  15.     ' is easy to display and to deterine what color is selected when
  16.     ' the ColorPalette is click, we set the Scale of the ColorPalette
  17.     ' to correspond to the number of color rows and columns.
  18.     '
  19.     Pic_ColorPalette.Scale (0, 0)-(16, 3)
  20.  
  21.     ' Display ColorPalette column by column
  22.     '
  23.     For i% = 0 To 15
  24.         '
  25.         ' Display a column of colors
  26.         '
  27.         Pic_ColorPalette.Line (i%, 0)-(i% + 1, 1), Colors(i%), BF
  28.         Pic_ColorPalette.Line (i%, 1)-(i% + 1, 2), Colors(i% + 16), BF
  29.         Pic_ColorPalette.Line (i%, 2)-(i% + 1, 3), Colors(i% + 32), BF
  30.  
  31.         ' Display vertical line to left of current columns to visually
  32.         ' divide the columns, but skip first column, since it is not
  33.         ' needed due to the Border of the color palette.
  34.         '
  35.         If i% Then Pic_ColorPalette.Line (i%, 0)-(i%, 3)
  36.     Next i%
  37.   
  38.     ' Display 2 horizontal lines to visually divide the color rows.
  39.     '
  40.     Pic_ColorPalette.Line (0, 1)-(16, 1)
  41.     Pic_ColorPalette.Line (0, 2)-(16, 2)
  42.  
  43. End Sub
  44.  
  45. ' Displays the entire or any portion of the grid, when the Grid option
  46. ' is active.  The 4 paramaters passed in, X1, Y1, X2, Y2, define the
  47. ' upper left and lower right corners of the area within the maginified
  48. ' Icon that needs the grid displayed.
  49. '
  50. Sub Display_Grid(hDCDest, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer)
  51. Dim DestX As Integer, DestY As Integer, DestWidth As Integer, DestHeight As Integer
  52.     ' The grid is not displayed if the icon is being viewed at normal
  53.     ' size, so check the current value of the scrollbar.
  54.     '
  55.     If Editor.Scrl_Zoom.Value > Editor.Scrl_Zoom.Min Then
  56.         DestX = X1 * PixelSize
  57.         DestY = Y1 * PixelSize
  58.         DestWidth = (X2 - X1 + 1) * PixelSize
  59.         DestHeight = (Y2 - Y1 + 1) * PixelSize
  60.         BitBlt hDCDest, X1 * PixelSize, Y1 * PixelSize, DestWidth, DestHeight, Editor.Pic_Grid.hDC, DestX, DestY, SRCAND
  61.     End If
  62.  
  63. End Sub
  64.  
  65. ' Whenever a new color is selected for either the left or right mouse
  66. ' button, or the StatusArea needs repainting, this routine is called to
  67. ' display the 4 small color squares at the bottom of the StatusArea
  68. ' which are filled with the current colors selected for the mouse buttons.
  69. '
  70. Sub Display_Mouse_Colors()
  71. Dim Middle As Integer, i As Integer, X1 As Integer, X2 As Integer, Y1 As Integer, Y2 As Integer
  72.  
  73.     ' Calculate the center of the Status bar
  74.     '
  75.     Middle = Editor.Pic_StatusArea.ScaleWidth \ 2
  76.  
  77.     ' Display the 4 color squares
  78.     '
  79.     For i = 0 To 3
  80.         '
  81.         ' The squares are centered within the left and right halfs of the
  82.         ' StatusArea, and the width and height are set equal to the Height
  83.         ' of the Option buttons used to select Left/Right or Screen/Inverse
  84.         ' colors, so we calculate the corners of the the Color squares
  85.         ' based on this information.
  86.         '
  87.         X1 = (i Mod 2) * Middle + (Middle - Editor.Opt_Mouse(i \ 2).Height) \ 2
  88.         X2 = X1 + Editor.Opt_Mouse(i \ 2).Height
  89.         Y1 = Editor.Opt_Mouse(i \ 2).Top
  90.         Y2 = Y1 + Editor.Opt_Mouse(i \ 2).Height
  91.  
  92.         ' Draw the color square
  93.         '
  94.         Editor.Pic_StatusArea.Line (X1, Y1)-(X2, Y2), MouseColors(i), BF
  95.  
  96.         ' Draw a black outline around the square
  97.         '
  98.         Editor.Pic_StatusArea.Line (X1, Y1)-(X2, Y2), BLACK, B
  99.     Next i
  100.         
  101.     ' Set the CurrentY value of the StatusArea back to that of the
  102.     ' location where the Mouse Coordinates are displayed, so this
  103.     ' does not have to be done within each MouseMove event of the
  104.     ' Edit area.
  105.     '
  106.     Editor.Pic_StatusArea.CurrentY = Editor.Pic_Icons(5).Top + Editor.Pic_Icons(5).Height + HIGHLIGHT + 1
  107.  
  108. End Sub
  109.  
  110. ' If a selection has been made, is being made, or a selection is
  111. ' being moved, or the Edit area needs repainting while a selection
  112. ' is active, this routine is called to display or redisplay a
  113. ' rectangle around the current selection.
  114. '
  115. Sub Draw_Selection_Rectangle()
  116. Dim XAdjust As Integer, YAdjust As Integer
  117.  
  118.     ' Set drawing mode to INVERSE since this routine also used to erase
  119.     ' the selection rectangle by simply drawing over the currently displayed
  120.     ' rectangle
  121.     '
  122.     Editor.Pic_Edit.DrawMode = INVERSE
  123.  
  124.     ' To distinguish between a selection and a selection that is
  125.     ' being moved, a Dotted line is used for a selection and a solid
  126.     ' line is used for a selection being moved.
  127.     '
  128.     If MovingSelection Then Editor.Pic_Edit.DrawStyle = SOLID Else Editor.Pic_Edit.DrawStyle = DOT
  129.  
  130.     ' To ensure the entire selection rectangle is visible, the rectangle
  131.     ' is adjusted inward 1 pixel from the right and bottom if the selection
  132.     ' contains either the right most column or bottom most row of pixels.
  133.     '
  134.     If X2Region >= PixelSize * 32 Then XAdjust = 1
  135.     If Y2Region >= PixelSize * 32 Then YAdjust = 1
  136.  
  137.     ' Draw the selection rectangle.
  138.     '
  139.     Editor.Pic_Edit.Line (X1Region, Y1Region)-(X2Region - XAdjust, Y2Region - YAdjust), , B
  140.     Editor.Pic_Edit.DrawStyle = SOLID
  141.  
  142. End Sub
  143.  
  144. ' When the currently selected Icon is changed or a new Icon is
  145. ' loaded into the currently selected Icon, the bitmaps that make
  146. ' of the Icons Mask and Image must be extracted and placed into
  147. ' picture controls where they can easily be edited.
  148. '
  149. Sub Extract_Image_And_Mask(Pic_Ctrl As Control)
  150. Dim IPic As IPicture
  151. Dim icoinfo As ICONINFO
  152. Dim PDesc As PICTDESC
  153. Dim hDCWork
  154. Dim hOldWorkBM
  155. Dim hNewBM
  156. Dim hOldMonoBM
  157.     GetIconInfo Pic_Ctrl.Picture, icoinfo
  158.     hDCWork = CreateCompatibleDC(0)
  159.     hNewBM = CreateCompatibleBitmap(Editor.hDC, 32, 32)
  160.     hOldWorkBM = SelectObject(hDCWork, hNewBM)
  161.     hOldMonoBM = SelectObject(hDCMono, icoinfo.hBMMask)
  162.     BitBlt hDCWork, 0, 0, 32, 32, hDCMono, 0, 0, SRCCOPY
  163.     SelectObject hDCMono, hOldMonoBM
  164.     SelectObject hDCWork, hOldWorkBM
  165.     With PDesc
  166.         .cbSizeofstruct = Len(PDesc)
  167.         .picType = PICTYPE_BITMAP
  168.         .Long1 = hNewBM
  169.     End With
  170.     OleCreatePictureIndirect PDesc, IID_IDispatch, 1, IPic
  171.     Editor.Pic_Mask = IPic
  172.     Set IPic = Nothing
  173.     PDesc.Long1 = icoinfo.hBMColor
  174.     OleCreatePictureIndirect PDesc, IID_IDispatch, 1, IPic
  175.     Editor.Pic_Image = IPic
  176.     DeleteObject icoinfo.hBMMask
  177.     DeleteDC hDCWork
  178. End Sub
  179.  
  180. ' Displays the selected help topic selected from either
  181. ' Editors;' or Viewer's help menu.
  182. '
  183. Sub Get_Help(HelpTopic As Integer)
  184. Dim dummy$
  185.     If HelpTopic = MID_USING_HELP Then
  186.         '
  187.         ' "Using Help" was selected so display the Standard Windows Help
  188.         ' Topic for "Using Help".
  189.         '
  190.         WinHelp Editor.hWnd, dummy$, HELP_HELPONHELP, 0
  191.     Else
  192.         ' A help topic other the "Using help" was selected.
  193.         '
  194.         
  195.          WinHelp Editor.hWnd, HelpFilePath, HELP_CONTEXT, CLng(HelpTopic)
  196.     End If
  197.  
  198. End Sub
  199.  
  200. Function Help_File_In_Path()
  201. Dim Path As String, CurrentDir As String, SemiColon As Integer, Found As Boolean
  202.  
  203.     On Error Resume Next
  204.     CurrentDir = App.Path
  205.     If Right$(CurrentDir, 1) <> "\" Then CurrentDir = CurrentDir + "\"
  206.     If Len(Dir$(CurrentDir + "IconWrks.HLP")) Then
  207.         HelpFilePath = CurrentDir + "IconWrks.HLP"
  208.         App.HelpFile = CurrentDir + "IconWrks.HLP"
  209.         Help_File_In_Path = True
  210.     Else
  211.         Path = Environ$("PATH")
  212.         If Path <> "" Then
  213.             If Right$(Path, 1) <> ";" Then Path = Path + ";"
  214.             SemiColon = InStr(Path, ";")
  215.             Do
  216.                 CurrentDir = Left$(Path, SemiColon - 1)
  217.                 If Right$(CurrentDir, 1) <> "\" Then CurrentDir = CurrentDir + "\"
  218.                 Path = Right$(Path, Len(Path) - SemiColon)
  219.                 SemiColon = InStr(Path, ";")
  220.                 Found = Len(Dir$(CurrentDir & "IconWrks.HLP"))
  221.             Loop While SemiColon And Not Found
  222.             Help_File_In_Path = Found
  223.         End If
  224.     End If
  225.     
  226.     On Error GoTo 0
  227.  
  228. End Function
  229.  
  230. ' The currently selected icon is distinguished by a solid square
  231. ' slightly larger than the icon itself, drawn behind the icon using
  232. ' the currently selected screen color.  This routine is called
  233. ' whenever this square needs to be displayed or redisplayed.
  234. '
  235. Sub HighLight_Current_Icon()
  236. Dim X1 As Integer, X2 As Integer, Y1 As Integer, Y2 As Integer
  237.     ' Erase the current selection square.
  238.     '
  239.     Editor.Pic_StatusArea.Line (0, 0)-(Editor.Pic_StatusArea.Width, Editor.Pic_Icons(4).Top + Editor.Pic_Icons(4).Height + 10), Editor.Pic_StatusArea.BackColor, BF
  240.  
  241.     ' Calculate the upper left and lower right corners of the selection square.
  242.     '
  243.     X1 = Editor.Pic_Icons(CurrentIcon).Left - HIGHLIGHT
  244.     X2 = Editor.Pic_Icons(CurrentIcon).Left + Editor.Pic_Icons(CurrentIcon).Width + HIGHLIGHT
  245.     Y1 = Editor.Pic_Icons(CurrentIcon).Top - HIGHLIGHT
  246.     Y2 = Editor.Pic_Icons(CurrentIcon).Top + Editor.Pic_Icons(CurrentIcon).Height + HIGHLIGHT
  247.   
  248.     ' Draw the solid selection square.
  249.     '
  250.     Editor.Pic_StatusArea.Line (X1, Y1)-(X2, Y2), MouseColors(2), BF
  251.  
  252.     ' Draw a Black outline around the square.
  253.     '
  254.     Editor.Pic_StatusArea.Line (X1, Y1)-(X2, Y2), BLACK, B
  255.  
  256.     If Editor.Menu_ViewSelection(MID_BORDER).Checked Then
  257.         '
  258.         ' Show edge of selected Icon by outline the icon
  259.         '
  260.         X1 = Editor.Pic_Icons(CurrentIcon).Left - 1
  261.         X2 = Editor.Pic_Icons(CurrentIcon).Left + Editor.Pic_Icons(CurrentIcon).Width
  262.         Y1 = Editor.Pic_Icons(CurrentIcon).Top - 1
  263.         Y2 = Editor.Pic_Icons(CurrentIcon).Top + Editor.Pic_Icons(CurrentIcon).Height
  264.         Editor.Pic_StatusArea.Line (X1, Y1)-(X2, Y2), BLACK, B
  265.     End If
  266.     
  267.     ' Set the CurrentY value of the StatusArea back to that of the
  268.     ' location where the Mouse Coordinates are displayed.
  269.     '
  270.     Editor.Pic_StatusArea.CurrentY = Editor.Pic_Icons(5).Top + Editor.Pic_Icons(5).Height + HIGHLIGHT + 1
  271.     
  272. End Sub
  273.  
  274. ' Inverts the specified control when an Icon from the Viewer is being
  275. ' dragged over the top of it, signaling that the Icon may be dropped
  276. ' on this control.
  277. '
  278. Sub Invert_Control(Ctrl As Control)
  279. Dim rectangle As RECT
  280.   
  281.     ' Calculate the Rectangle to invert
  282.     '
  283.     rectangle.Right = Ctrl.ScaleWidth
  284.     rectangle.bottom = Ctrl.ScaleHeight
  285.  
  286.     ' Invert the rectangle
  287.     '
  288.      InvertRect Ctrl.hDC, rectangle
  289.  
  290. End Sub
  291.  
  292. ' This routine is used to tie the Viewer and the Editor together.  When
  293. ' and Icon is selected in one of the various ways from within the Viewer,
  294. ' or an Icon is dragged from the Viewer and dropped on a valid location
  295. ' of the Editor, this routine is called either from the Viewer or from
  296. ' the Editor (depending on how the Icon was selected), to load the
  297. ' selected icon into the Editor.
  298. '
  299. Sub Load_An_Icon()
  300.  
  301.     ' Check if the new icon would be replacing an existing Icon which
  302.     ' has been changed since the last time it has been saved, and if
  303.     ' so, ask the user if it is ok to discard the changes.
  304.     '
  305.     If Ok_To_Discard_Changes() Then
  306.         '
  307.         ' Get the Filename and Fullpath to the icon, and set its
  308.         ' Changed flag to FALSE.
  309.         '
  310.         ICONINFO(CurrentIcon).FileName = Viewer.File_FileList.FileName
  311.         ICONINFO(CurrentIcon).FullPath = Viewer.File_FileList.Path
  312.         ICONINFO(CurrentIcon).Changed = False
  313.  
  314.         ' Place the Name and Path of the Icon in the corresponding menu
  315.         ' item in the Editors Icons menu.
  316.         '
  317.         Editor.Menu_IconsSelection(CurrentIcon).Caption = "&" + Format$(CurrentIcon + 1) + " - [" + Viewer.File_FileList.Path + "]" + A_TAB + Viewer.File_FileList.FileName
  318.  
  319.         ' Load the Icon into the selected icon in the StatusArea.
  320.         '
  321.         Editor.Pic_Icons(CurrentIcon).Picture = LoadPicture(Viewer.File_FileList.FileName)
  322.  
  323.         ' If the Menu option is set, bring the Editor to the Foreground
  324.         ' when an Icon is loaded.
  325.         '
  326.         If Editor.Menu_ViewSelection(MID_FOCUS).Checked Then Editor.Show
  327.  
  328.         ' Simulate clicking the Icon in the StatusArea to take care of the
  329.         ' visual part of selection.
  330.         '
  331.         Select_New_Icon
  332.         Editor.Pic_ToolPalette.Refresh
  333.     Else
  334.         ' Do not discard the changes of the existing icon.
  335.         '
  336.         Editor.Pic_Icons(CurrentIcon).Cls
  337.         Magnify_Icon 0, 0, 31, 31
  338.     End If
  339.  
  340. End Sub
  341.  
  342. ' There are various situations when all or part of the current icon
  343. ' needs to be magnified and displayed in the editing area.  this
  344. ' routine is called to perform the magnification.  The Windows API
  345. ' routine, StretchBlt() is used to perform the magnification.
  346. '
  347. Sub Magnify_Icon(X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer)
  348. Dim DestX As Integer, DestY As Integer, DestWidth As Integer, DestHeight As Integer
  349. Dim srcWidth As Integer, srcHeight As Integer
  350.     
  351.     ' Ensure that X1 and Y1 refer to the upper left corner and X2 and Y2
  352.     ' refer to the lower right corner of the area to be magnified.
  353.     '
  354.     If X1 > X2 Then Swap_Values X1, X2
  355.     If Y1 > Y2 Then Swap_Values Y1, Y2
  356.  
  357.     ' The area to be magnified must not contain any pixels outside
  358.     ' of the Icon itself, so we must check for this situation and
  359.     ' adjust the values if neccessary.
  360.     '
  361.     If X1 < 0 Then X1 = 0
  362.     If X2 > 31 Then X2 = 31
  363.     If Y1 < 0 Then Y1 = 0
  364.     If Y2 > 31 Then Y2 = 31
  365.  
  366.     ' Calculate the width and height values of the source bitmap
  367.     '
  368.     srcWidth = X2 - X1 + 1
  369.     srcHeight = Y2 - Y1 + 1
  370.  
  371.     ' Calculate the destinations width, height and upper left corner
  372.     ' of the area to be magnified.
  373.     '
  374.     DestX = X1 * PixelSize
  375.     DestY = Y1 * PixelSize
  376.     DestWidth = srcWidth * PixelSize
  377.     DestHeight = srcHeight * PixelSize
  378.   
  379.     ' Magnify the icon.  We StretchBlt() from the image of the Icon in
  380.     ' the StatusArea to the Editing area.  Since we always maintain the
  381.     ' size of the Editing area a multiple of 32 (Size of an Icon), the
  382.     ' magnified icon will always be a perfect enlargement of the Icons
  383.     ' image.
  384.     '
  385.     If ImageSize = 1024 Then
  386.         '
  387.         StretchBlt Editor.Pic_Edit.hDC, DestX, DestY, DestWidth, DestHeight, Editor.Pic_Icons(CurrentIcon).hDC, X1, Y1, srcWidth, srcHeight, SRCCOPY
  388.         '
  389.         ' Redisplay the grid in the area that was magnified if the Grid option
  390.         ' is currently selected.
  391.         '
  392.         If Editor.Menu_ViewSelection(MID_GRID).Checked Then Display_Grid (Editor.Pic_Edit.hDC), X1, Y1, X2, Y2
  393.     Else
  394.         '
  395.         StretchBlt Editor.Pic_EditTemp.hDC, DestX, DestY, DestWidth, DestHeight, Editor.Pic_Icons(CurrentIcon).hDC, X1, Y1, srcWidth, srcHeight, SRCCOPY
  396.         '
  397.         ' Redisplay the grid in the area that was magnified if the Grid option
  398.         ' is currently selected.
  399.         '
  400.         If Editor.Menu_ViewSelection(MID_GRID).Checked Then Display_Grid (Editor.Pic_EditTemp.hDC), X1, Y1, X2, Y2
  401.         BitBlt Editor.Pic_Edit.hDC, DestX, DestY, DestWidth, DestHeight, Editor.Pic_EditTemp.hDC, DestX, DestY, SRCCOPY
  402.     End If
  403.  
  404.     ' Check if there is an active selection in the Editing area.  If so,
  405.     ' we must also redisplay the contents of the selection since the above
  406.     ' StretchBlt() operation may have entirely or partially covered up
  407.     ' the selection.
  408.     '
  409.     If MovingSelection Then
  410.         '
  411.         ' Calculate the width and height values of the source bitmap
  412.         ' containing the selection.  Always maintained in the global values
  413.         ' X1SelectFrom, Y1SelectFrom, X2SelectFrom, and Y2SelectFrom
  414.         '
  415.         srcWidth = X2SelectFrom - X1SelectFrom
  416.         srcHeight = Y2SelectFrom - Y1SelectFrom
  417.         
  418.         ' Calculate the destinations width and height of the area to be magnified.
  419.         '
  420.         DestWidth = srcWidth * PixelSize
  421.         DestHeight = srcHeight * PixelSize
  422.  
  423.         ' Determine type of Selection: Opaque, or Not Opaque.
  424.         '
  425.         If Opaque Then
  426.             '
  427.             ' Opaque selection: Magnify the selection bitmap including any Screen
  428.             ' or Inverse Screen attributes
  429.             '
  430.             StretchBlt Editor.Pic_Edit.hDC, X1Region, Y1Region, DestWidth, DestHeight, Editor.Pic_Work.hDC, X1SelectFrom, Y1SelectFrom, srcWidth, srcHeight, SRCCOPY
  431.         Else
  432.             ' None Opaque Selection: Magnify the selection bitmap but do not include
  433.             ' any Screen or Inverse Screen attributes.
  434.             '
  435.             StretchBlt Editor.Pic_Edit.hDC, X1Region, Y1Region, DestWidth, DestHeight, Editor.Pic_TempMask.hDC, X1SelectFrom, Y1SelectFrom, srcWidth, srcHeight, SRCAND
  436.             StretchBlt Editor.Pic_Edit.hDC, X1Region, Y1Region, DestWidth, DestHeight, Editor.Pic_TempImage.hDC, X1SelectFrom, Y1SelectFrom, srcWidth, srcHeight, SRCINVERT
  437.         End If
  438.     End If
  439.   
  440.     ' Redisplay the selection rectangle if currently making a selection
  441.     '
  442.     If Selecting Then Draw_Selection_Rectangle
  443.  
  444. End Sub
  445.  
  446. ' A Sub Main is used instead of a startup form to allow the user
  447. ' to startup either the Editor or Viewer as the main form.  The
  448. ' Editor is the Default main form, however starting IconWorks
  449. ' with a command line of "v" or "V" will start IconWorks with
  450. ' the Viewer as the main form.
  451. '
  452. Sub Main()
  453.   
  454.     ' Check video mode.  If less than EGA, terminate Iconworks
  455.     '
  456.     If Screen.Height < EGA_HEIGHT Then
  457.         MsgBox "IconWorks requires EGA or Better.", 16, "IconWorks"
  458.         End
  459.     Else
  460.         ' Since you cannot assign values like TAB, CR, and LF to string
  461.         ' constants, the values of TAB and CRLF which are used frequently
  462.         ' thoughout IconWorks when displaying messages, these values are
  463.         ' are assigned to the global string values of A_TAB and CRLF
  464.         '
  465.         A_TAB = Chr$(9)
  466.         CRLF = Chr$(13) + Chr$(10)
  467.  
  468.         If Not Help_File_In_Path() Then
  469.             Text = "ICONWRKS.HLP not found in your path." + CRLF + CRLF
  470.             Text = Text + "Windows searches your PATH environment variable for help files, "
  471.             Text = Text + "so you need to copy ICONWRKS.HLP to a directory included in your "
  472.             Text = Text + "PATH if you wish to obtain help while running IconWorks."
  473.             MsgBox Text, 48, "IconWorks help not available"
  474.         End If
  475.         
  476.         With IID_IDispatch
  477.             .Data1 = &H20400
  478.             .Data4(0) = &HC0
  479.             .Data4(7) = &H46
  480.         End With
  481.         ' Determine which form to use as main form, Editor) or the Viewer
  482.         '
  483.         If (Command$ = "") Or (UCase$(Left$(Command$, 1)) <> "V") Then
  484.             '
  485.             ' Editor is main form
  486.             '
  487.             MainForm = ICONWORKS_EDITOR
  488.             Editor.Show
  489.         Else
  490.             ' Viewer is main form
  491.             '
  492.             MainForm = ICONWORKS_VIEWER
  493.             Viewer.Show
  494.         End If
  495.     End If
  496.  
  497. End Sub
  498.  
  499. ' Determines if an Icon has been modified since it was saved last, and
  500. ' prompts the user if so.
  501. '
  502. Function Ok_To_Discard_Changes()
  503.  
  504.     Text = ""
  505.     Ok_To_Discard_Changes = True
  506.  
  507.     ' Check if Icon has changed since it was last saved.
  508.     '
  509.     If ICONINFO(CurrentIcon).Changed Then
  510.         '
  511.         ' Inform user icon has been modifyied.
  512.         '
  513.         Text = Text + "Icon:" + A_TAB + "#" + Format$(CurrentIcon + 1) + CRLF
  514.         Text = Text + "Name:" + A_TAB + ICONINFO(CurrentIcon).FileName + CRLF
  515.         Text = Text + "Path:" + A_TAB + ICONINFO(CurrentIcon).FullPath + CRLF + CRLF
  516.         Text = Text + "Discard changes?"
  517.         Ok_To_Discard_Changes = MsgBox(Text, 36, "ICON HAS CHANGED") = MBYES
  518.     End If
  519.  
  520. End Function
  521.  
  522. ' Removes various menu items from the System menu of the specified Form.
  523. '
  524. Sub Remove_Items_From_Sysmenu(A_Form As Form)
  525. Dim hSysMenu
  526.  
  527.     ' Obtain the handle to the forms System menu
  528.     '
  529.     hSysMenu = GetSystemMenu(A_Form.hWnd, 0)
  530.   
  531.     ' Remove all but the MOVE and CLOSE options.  The menu items
  532.     ' must be removed starting with the last menu item.
  533.     '
  534.     RemoveMenu hSysMenu, 8, MF_BYPOSITION  'Switch to
  535.     RemoveMenu hSysMenu, 7, MF_BYPOSITION  'Separator
  536.     RemoveMenu hSysMenu, 5, MF_BYPOSITION 'Separator
  537.  
  538. End Sub
  539.  
  540. ' The rectanglular Region which is always defined by the global
  541. ' variables X1Region, Y1Region, X2Region, and Y2Region, is the
  542. ' basis for most of the tools in the toolpalette, and is frequently
  543. ' scaled from the scale of the Editing area down to the scale of
  544. ' the actual Icon, and in the reverse direction.  This routine
  545. ' performs the neccessary scaling, in either direction based on
  546. ' the value of *ToIcon*.
  547. '
  548. Sub Scale_Region(ToIcon As Boolean, X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer, CheckX1Y1 As Boolean)
  549.   
  550.     ' Determine which direction to scale
  551.     '
  552.     If ToIcon Then
  553.         '
  554.         ' Scale Global variables down to and Icon
  555.         '
  556.         X1 = X1Region \ PixelSize
  557.         Y1 = Y1Region \ PixelSize
  558.         X2 = X2Region \ PixelSize
  559.         Y2 = Y2Region \ PixelSize
  560.     
  561.         ' If requested, ensure X1 and Y1 refer to upper left corner
  562.         ' and X2 and Y2 refer to the lower right corner of the Region.
  563.         '
  564.         If CheckX1Y1 Then
  565.             If X1 > X2 Then Swap_Values X1, X2
  566.             If Y1 > Y2 Then Swap_Values Y1, Y2
  567.         End If
  568.     Else
  569.         ' Scale the values X1, Y1, X2, Y2 upto the Editing
  570.         ' area and assign to global variables
  571.         '
  572.         X1Region = X1 * PixelSize
  573.         Y1Region = Y1 * PixelSize
  574.         X2Region = X2 * PixelSize
  575.         Y2Region = Y2 * PixelSize
  576.     End If
  577.   
  578.  
  579. End Sub
  580.  
  581. ' When a new Icon from one of the 6 displayed within the StatusArea is selected
  582. ' or if a new icon is selected from the viewer to be edited, this routine is
  583. ' called to take care of the visual changes within the StatusArea.
  584. '
  585. Sub Select_New_Icon()
  586.     
  587.     Selecting = False
  588.     MovingSelection = False
  589.  
  590.     HighLight_Current_Icon
  591.  
  592.     Extract_Image_And_Mask Editor.Pic_Icons(CurrentIcon)
  593.       
  594.     ' Set the Undo Icon to the newly selected Icon.
  595.     '
  596.     Update_Icon Editor.Pic_Undo
  597.  
  598.     ' Display the icon in the editing area
  599.     '
  600.     Magnify_Icon 0, 0, 31, 31
  601.  
  602.     ' Display the Filename of the selected icon in the Editor's Titlebar
  603.     '
  604.     Editor.Caption = "IconWorks Editor: " + Format$(CurrentIcon + 1) + " - " + ICONINFO(CurrentIcon).FileName
  605.  
  606. End Sub
  607.  
  608. ' Since the Swap statement is not supported by Visual Basic, this
  609. ' routine is used to perform the task of swapping two integer values.
  610. '
  611. Sub Swap_Values(Param1 As Integer, Param2 As Integer)
  612. Dim Temp As Integer
  613.     Temp = Param1
  614.     Param1 = Param2
  615.     Param2 = Temp
  616.  
  617. End Sub
  618.  
  619. ' This routine is used by the SaveFileDlg and the Viewer to update the
  620. ' filespec displayed in the FileName TextBox whenever the forms Directory
  621. ' ListBox control is Single Clicked.  Since a Single click does not
  622. ' actually make a selection, this routine is called in response to a
  623. ' single click to display what would be the result if a double click
  624. ' is performed or if Enter is pressed.
  625. '
  626. Sub UpDate_FileSpec(A_Form As Form)
  627. Dim SelPath As String, CurPath As String, Slash As String, i As Integer
  628.  
  629.     CurPath = A_Form.Lbl_CurrentDirectory.Caption
  630.     SelPath = A_Form.Dir_DirectoryList.List(A_Form.Dir_DirectoryList.ListIndex)
  631.  
  632.     Select Case A_Form.Dir_DirectoryList.ListIndex
  633.         
  634.         Case Is >= 0
  635.             '
  636.             ' A subdirectory from the Current directory was selected
  637.             '
  638.             i = Right$(CurPath, 1) <> "\"
  639.             A_Form.Txt_FileName.Text = Right$(SelPath, Len(SelPath) - Len(CurPath) + i) + "\" + A_Form.File_FileList.Pattern
  640.         
  641.         Case Is = -1
  642.             '
  643.             ' The current directory was selected
  644.             '
  645.             A_Form.Txt_FileName.Text = A_Form.File_FileList.Pattern
  646.         
  647.         Case Is < -1
  648.             '
  649.             ' A parent directory of the Current directory was selected
  650.             '
  651.             SelPath = Right$(SelPath, Len(SelPath) - 2)
  652.             If Len(SelPath) > 1 Then Slash = "\"
  653.             A_Form.Txt_FileName.Text = SelPath + Slash + A_Form.File_FileList.Pattern
  654.     
  655.     End Select
  656.  
  657. End Sub
  658.  
  659. ' We do not actually modify the Icon directly, but modify the Mask and Image
  660. ' bitmaps that make up the Icon. So these bitmaps must be copied over the icons
  661. ' Mask and Image bitmaps after each edit to reflect the change in the actual
  662. ' icon displayed in the StatusArea.
  663. '
  664. Sub Update_Icon(Pic_Ctrl As Control)
  665. Dim hOldMonoBM
  666. Dim hDCWork
  667. Dim hBMOldWork
  668. Dim hBMWork
  669. Dim PDesc As PICTDESC
  670. Dim icoinfo As ICONINFO
  671. Dim IPic As IPicture
  672.     BitBlt hDCMono, 0, 0, 32, 32, Editor.Pic_Mask.hDC, 0, 0, SRCCOPY
  673.     SelectObject hDCMono, hBMOldMono
  674.     hDCWork = CreateCompatibleDC(0)
  675.     With Pic_Ctrl
  676.         hBMWork = CreateCompatibleBitmap(Editor.hDC, .Width, .Height)
  677.     End With
  678.     hBMOldWork = SelectObject(hDCWork, hBMWork)
  679.     BitBlt hDCWork, 0, 0, 32, 32, Editor.Pic_Image.hDC, 0, 0, SRCCOPY
  680.     SelectObject hDCWork, hBMOldWork
  681.     With icoinfo
  682.         .fIcon = 1
  683.         .xHotspot = 16
  684.         .yHotspot = 16
  685.         .hBMMask = hBMMono
  686.         .hBMColor = hBMWork
  687.     End With
  688.     With PDesc
  689.         .cbSizeofstruct = Len(PDesc)
  690.         .picType = PICTYPE_ICON
  691.         .Long1 = CreateIconIndirect(icoinfo)
  692.     End With
  693.     OleCreatePictureIndirect PDesc, IID_IDispatch, 1, IPic
  694.     Pic_Ctrl = IPic
  695.     hBMOldMono = SelectObject(hDCMono, hBMMono)
  696.     DeleteDC hDCWork
  697.     ' Set Changed Flag to TRUE since it has been modified.
  698.     '
  699.     If Pic_Ctrl.Tag <> Editor.Pic_Undo.Tag Then ICONINFO(CurrentIcon).Changed = True
  700.  
  701. End Sub
  702.  
  703. ' When either the Editors ColorPalette or the ColorPalette Forms
  704. ' Color Palette is clicked, this routine is called to set the selected
  705. ' color into the Mouse colors, and invoke the ColorPalette Form in
  706. ' the case of a Double Click event on the Editors Color Palette.
  707. '
  708. Sub Update_Mouse_Colors(Button, X As Single, Y As Single)
  709. Dim color As Long, SolidColor As Long, Index As Integer, i As Integer
  710.  
  711.     ' The ColorPalettes are a single picture control, so we must calculate
  712.     ' the color selected based on the coordinates of the mouse.
  713.     '
  714.     ColorIndex = Fix(X) + Fix(Y) * 16
  715.  
  716.     ' Obtain color from color array
  717.     '
  718.     color = Colors(ColorIndex)
  719.  
  720.     ' VB only supports 16 color mode, so we must obtain the nearest Solid
  721.     ' color to the selected color since the Screen and Inverse colors cannot
  722.     ' be set to dithered colors.
  723.     '
  724.     SolidColor = GetNearestColor(Editor.hDC, color)
  725.  
  726.     If DoubleClicked Then
  727.         '
  728.         ' The Editors ColorPalette was Double Clicked, so reset the Flag
  729.         ' and invoke the ColorPalette Form.
  730.         '
  731.         DoubleClicked = False
  732.         ColorPalette.Show
  733.  
  734.         ' The ColorPalette Forms initialization is done within the
  735.         ' GotFocus Event for its ColorPalette Picture control, so we
  736.         ' must give that Picture Control the focus.
  737.         '
  738.         ColorPalette.Pic_ColorPalette.SetFocus
  739.  
  740.     ElseIf Editor.Opt_Mouse(SCREEN_COLORS).Value And (color <> SolidColor) Then
  741.         '
  742.         ' An attempt to select a Dithered color into the Screen or Inverse
  743.         ' colors was made, so Prompt the user and do not allow the selection
  744.         '
  745.         MsgBox "Screen and Inverse colors can only be set to solid colors", 16, "Error"
  746.     Else
  747.         ' Obtain the the index of the corresponding mouse Color:
  748.         '   0 - Left Mouse Color
  749.         '   1 - Right Mouse Color
  750.         '   2 - Screen Color
  751.         '   3 - Inverse Screen Color
  752.         '
  753.         Index = Editor.Opt_Mouse(SCREEN_COLORS).Value * (-2) + Button - 1
  754.  
  755.         ' Replace the Mouse color with the new color
  756.         '
  757.         MouseColors(Index) = Colors(ColorIndex)
  758.  
  759.         ' Changing either the Screen Color or Inverse Screen Color also
  760.         ' changes the other so if either the Screen or Inverse color was
  761.         ' changed, we must change the other to its inverse.
  762.         '
  763.         If Index >= 2 Then
  764.             Editor.Pic_Icons(0).PSet (1, 1), MouseColors(Index)
  765.             MouseColors(Abs(Index - 5)) = Editor.Pic_Icons(0).Point(1, 1)
  766.             Editor.Pic_Icons(0).Cls
  767.         End If
  768.     
  769.         If Editor.Opt_Mouse(SCREEN_COLORS).Value Then
  770.             '
  771.             ' The Screen or Inverse Screen color was changed, so we must change
  772.             ' the BackColor of all 6 icons in the StatusArea and the Undo Icon to
  773.             ' the new Screen Color and then redisplay the selected Icon in the
  774.             ' Editing area.
  775.             '
  776.             HighLight_Current_Icon
  777.             For i = 0 To 5
  778.                 Editor.Pic_Icons(i).BackColor = MouseColors(2)
  779.             Next
  780.             Editor.Pic_Undo.BackColor = MouseColors(2)
  781.             Magnify_Icon 0, 0, 31, 31
  782.         End If
  783.  
  784.     End If
  785.  
  786.     ' Diplay the New Mouse colors at the Bottom of the StatusArea
  787.     '
  788.     Display_Mouse_Colors
  789.  
  790. End Sub
  791.  
  792. ' Selecting a new drive from the list of a Drive controls drop
  793. ' down list does not generate an error if the drive is not ready,
  794. ' so when a new drive is selected, we determine if it is ready
  795. ' or not.  This routine validates the selected drive and is use
  796. ' by both the SaveFileDlg's and Viewers's Drive control
  797. '
  798. Sub Validate_And_Change_Drives(A_Form As Form)
  799.     
  800.     On Error Resume Next
  801.     Err = False
  802.  
  803.     ' Invoking the Dir$() function with the selected drive will generate
  804.     ' an error if the drive is not ready.  We don't care about the return
  805.     ' value, we just care if an error is generated or not.
  806.     '
  807.     Dir$ Left$(A_Form.Drv_DriveList.Drive, 2)
  808.  
  809.     If Err Then
  810.         '
  811.         ' The drive was not ready, so prompt the user
  812.         '
  813.         Beep
  814.         MsgBox Error$(Err), 16, "IconWorks - ERROR: " + Format$(Err)
  815.  
  816.         ' Reset the Drive Control back to its previously selected drive
  817.         '
  818.         A_Form.Drv_DriveList.Drive = Left$(A_Form.Dir_DirectoryList.Path, 2)
  819.     Else
  820.         ' The drive is ready, so change to that drive
  821.         '
  822.         ChDrive A_Form.Drv_DriveList.Drive
  823.         A_Form.Dir_DirectoryList.Path = CurDir$
  824.     End If
  825.   
  826.     On Error GoTo 0
  827.  
  828. End Sub
  829.  
  830. ' When a filespec is entered into either the Viewer's Filename
  831. ' TextBox or the SaveFileDlg's Filename TextBox, this routine is
  832. ' called to validate the FileSpec.  The name and path, if one is
  833. ' given, is validated.  If a valid FileSpec to an actual file is
  834. ' entered and the file does not exist, the return value depends
  835. ' on which Form called this routine, since a if called from the
  836. ' SaveFileDlg a "File Not Found" error is generated but that is
  837. ' OK since a file does not have to exist to write to it.  However,
  838. ' if called from the Viewer, the same error will be generated but
  839. ' in this case the file must exists since the Viewer is wants to
  840. ' open the file for editing.
  841. '
  842. Function Validate_FileSpec(AForm As Form, MustExist)
  843. Dim Temp As String, PeriodPos As Integer, LeftOfPeriod$
  844.  
  845.     ' Enable error trapping
  846.     '
  847.     On Error GoTo ErrorInSpec
  848.  
  849.     Validate_FileSpec = False
  850.  
  851.     ' Check for valid DOS Path and Filenames.
  852.     '
  853.     Temp = Dir$(AForm.Txt_FileName.Text)
  854.  
  855.     ' The following statement does alot.  It the FileSpec contains
  856.     ' a Path, the FileSpec will be parsed and the Path will be assign
  857.     ' to the File ListBox's Path property.  If the FileSpec contains
  858.     ' Wild card characters, it will be assign to the File ListBox's
  859.     ' pattern property.  If the FileSpec contains a valid file name
  860.     ' and the file exists, a Double Click event will automatically be
  861.     ' generated for the File ListBox.  If the File does not exist,
  862.     ' a "File Not Found" error will be generated which we trap.
  863.     '
  864.     AForm.File_FileList.FileName = AForm.Txt_FileName.Text
  865.   
  866. Exit_The_Function:
  867.  
  868.     ' Turn off error trapping and exit the function
  869.     '
  870.     On Error GoTo 0
  871.     Exit Function
  872.  
  873. ErrorInSpec:
  874.     If (Err <> FILE_NOT_FOUND) Or ((Err = FILE_NOT_FOUND) And MustExist) Then
  875.         '
  876.         ' An error other than "File Not Found" occured, or the error
  877.         ' "File Not Found" occured and this Function was invoked from
  878.         ' the Viewer which requires the file to exist.
  879.         '
  880.         Beep
  881.         MsgBox Error$(Err), 16, "IconWorks - ERROR: " + Format$(Err)
  882.     Else
  883.         ' The FileSpec entered contain no errors other than maybe
  884.         ' "File Not Found".
  885.         '
  886.         If Err = FILE_NOT_FOUND Then
  887.             ' A Valid filename was entered in the SaveFileDlg which did not exist
  888.             ' so the File Control did not parse the FileSpec for us.  Since the
  889.             ' FileSpec could contain a path specification, force File control
  890.             ' to parse the Filename string for us by changing last character to
  891.             ' an asterisk "*" and assign the modified FileSpec to the File Controls
  892.             ' FileName property.  The asterisk "*" makes the Filename appear as a
  893.             ' FileSpec rather than a Filename to the File ListBox and it will parse
  894.             ' it for us whether there are any matching files or not.  After it has
  895.             ' been parsed, we change the "*" back to its previous value.
  896.             '
  897.             Temp = Right$(AForm.Txt_FileName.Text, 1)
  898.             AForm.File_FileList.FileName = Left$(AForm.Txt_FileName.Text, Len(AForm.Txt_FileName.Text) - 1) + "*"
  899.             AForm.Txt_FileName.Text = Left$(AForm.File_FileList.Pattern, Len(AForm.File_FileList.Pattern) - 1) + Temp
  900.             
  901.             ' This checks to see that that file name that has been parsed
  902.             ' is a valid DOS file name
  903.  
  904.              PeriodPos = InStr(1, AForm.Txt_FileName.Text, ".")
  905.              If PeriodPos <> 0 Then
  906.                 LeftOfPeriod$ = Left$(AForm.Txt_FileName.Text, PeriodPos - 1)
  907.              Else
  908.                LeftOfPeriod$ = AForm.Txt_FileName.Text
  909.              End If
  910.              If Len(AForm.Txt_FileName.Text) > 8 Then
  911.                      Resume Exit_The_Function
  912.             End If
  913.             Else
  914.         End If
  915.         Validate_FileSpec = True
  916.     End If
  917.     Resume Exit_The_Function
  918.  
  919. End Function
  920.  
  921. ' Saves the current icon to disk, and updates the Icon menu and
  922. ' Editors title bar with the new Icons filename.
  923. '
  924. Sub Write_Icon_To_File(FullPath As String, FileName As String)
  925.   
  926.     ' Save new Filename and Path information for the Icon
  927.     '
  928.     ICONINFO(CurrentIcon).FileName = FileName
  929.     ICONINFO(CurrentIcon).FullPath = FullPath
  930.     ICONINFO(CurrentIcon).Changed = False
  931.  
  932.     ' Display the Icons Filename and Path in the Editors Icon menu
  933.     '
  934.     Editor.Menu_IconsSelection(CurrentIcon).Caption = "&" + Format$(CurrentIcon + 1) + " - [" + FullPath + "]" + A_TAB + FileName
  935.  
  936.     ' Display the Icons Filename in the Editors TitleBar
  937.     '
  938.     Editor.Caption = "IconWorks Editor: " + Format$(CurrentIcon + 1) + " - " + FileName
  939.  
  940.     ' Save the Icon to the specified File in the Specified Directory
  941.     '
  942.     If Right$(FullPath, 1) <> "\" Then FullPath = FullPath + "\"
  943.     SavePicture Editor.Pic_Icons(CurrentIcon).Picture, FullPath + FileName
  944.  
  945. End Sub
  946.  
  947.